1 Document
1.1 浏览器环境,规格
1.1.1 整体结构
下图为JavaScript 在浏览器中运行时的结构图,Window
作为根对象,承担的两个角色:
window
是JavaScript的全局对象;window
是“浏览器窗口”,控制浏览器窗口的各种方法都绑定在window
上。
1.1.2 Document Object Model
DOM是文档对象模型。利用DOM的概念,把网页中所有的内容都被表示为可以修改的对象。DOM规范解释了文档的结构,提供了操作文档的对象和方法,不仅支持浏览器,也对其他设备提供支持。
其中,Document
对象是页面的主要“入口点”,可以使用它来更改或创建页面上的任何内容。
也就是说,
- JavaScript利用DOM操作页面的内容,不恰当的说,就是操作“HTML”部分;
- JavaScript利用CSSOM(CSS Object Model)操作页面的样式,也就是“CSS”部分,但是不常用。
1.1.3 Browser Object Model
BOM是浏览器对象模型。BOM的概念规定了主机环境(浏览器)除处理document(归BOM管)以外,所有内容以及这些内容的对象。
例如:
1.1.4 总结
以下是各个标准:
- DOM规范:描述文档的结构、操作和事件,详见 https://dom.spec.whatwg.org。
- CSSOM规范:描述样式表和样式规则,对它们进行的操作,以及它们与文档的绑定,详见 https://www.w3.org/TR/cssom-1/。
- HTML规范:描述 HTML 语言(例如标签)以及 BOM(浏览器对象模型)— 各种浏览器函数:
setTimeout
,alert
,location
等,详见 https://html.spec.whatwg.org。它采用了 DOM 规范,并使用了许多其他属性和方法对其进行了扩展。
此 外,某些类被分别描述在 https://spec.whatwg.org/。
-
当你想要了解某个属性或方法时,使用Mozilla 手册 。
-
要查找某些内容时,可以使用互联网搜索 “WHATWG [term]” 或 “MDN [term]”,
例如 https://google.com?q=whatwg+localstorage,https://google.com?q=mdn+localstorage。
1.2 DOM树
在DOM文档对象模型中,HTML文档的主干是由一个个标签(tag)组成的,每个标签都声明为一个对象,这些标签对象和其他对象共同构成了一个DOM树结构。用JavaScript对对象进行修改,通过修改DOM文档,最终修改页面内容。
1.2.1 举例
一个简单的document,用HTML代码则表示如下结构。
<!DOCTYPE HTML>
<html>
<head>
<title>About elk</title>
</head>
<body>
The truth about elk.
</body>
</html>
如果用DOM模型的树形结构表示,可以想象为如下结构:
在HTML中的“标签(tag)”和其他元素,在DOM模型中则表示为“对象”,在树形结构中则称之为“节点”。
1.2.2 节点类型
**HTML 中的所有内容,都会成为 DOM 的一部分。**DOM中含有的节点类型,一共有[12种](DOM Standard (whatwg.org)):
// 摘录12种节点类型
const unsigned short ELEMENT_NODE = 1; // 元素节点(常见)
const unsigned short ATTRIBUTE_NODE = 2; // 属性节点(常见)
const unsigned short TEXT_NODE = 3; // 文本节点(常见)
const unsigned short CDATA_SECTION_NODE = 4; // CDATASection节点
const unsigned short ENTITY_REFERENCE_NODE = 5; // legacy EntityReference节点(历史)
const unsigned short ENTITY_NODE = 6; // legacy Entity节点(历史)
const unsigned short PROCESSING_INSTRUCTION_NODE = 7; // ProcessingInstruction节点
const unsigned short COMMENT_NODE = 8; // 注释节点(常见)
const unsigned short DOCUMENT_NODE = 9; // 文档节点(常见)
const unsigned short DOCUMENT_TYPE_NODE = 10; // DocumentType节点
const unsigned short DOCUMENT_FRAGMENT_NODE = 11; // 文档片段节点
const unsigned short NOTATION_NODE = 12; // legacy Notation节点(历史)
常见的节点类型为:
#document
:Document node 文档节点,代表整个网页,是网页内容的入口,也是DOM树的根节点。#元素名
:标签被称为 Element node 元素节点。<html>
是根元素,也称为“顶级标签”,除此之外,还有子节点、父节点、兄弟节点等概念;#text
:文本被称为 Text node文本节点,它一定被某个元素节点包含;#comment
:Comment node 注释节点,即HTML代码中的注释部分,会被创建为一个注释节点;- ``:Attributes node 属性节点。对每一个元素设置的属性,都在创建的属性节点中保存。
1.2.3 特征
自动修正
和HTML的灵活性对应,当浏览器遇到不正确的HTML,会在形成DOM时自动更正它:
- 如果HTML中,没有顶级标签或
<body>
标签,则形成DOM时自动创建<html>
对象或<body>
对象。 - 如果HTML中,有没有闭合的标签,则会自动闭合。
<p>xxx</p>
与控制台交互
在我们处理 DOM 时,我们可能还希望对其应用 JavaScript。例如:获取一个节点并运行一些代码来修改它,以查看结果。以下是在元素(Elements)选项卡和控制台(Console)之间切换的一些技巧。
首先,打开 elks.html:
- 在元素(Elements)选项卡中选择第一个
<li>
。 - 按下 Esc — 它将在元素(Elements)选项卡下方打开控制台(Console)。
现在最后选中的元素可以通过 $0
来进行操作,先前选择的是 $1
,等。
我们可以对它们执行一些命令。例如,$0.style.background = 'red'
使选定的列表项(list item)变成红色,像这样:
1.3 遍历DOM
修 改页面内容,就是通过对DOM进行操作;对 DOM 的所有操作,要先获取对应的DOM对象;获取DOM对象,都是以 document
对象开始。它是 DOM 的主“入口点”,从它我们可以访问任何节点。
对象之前存在一定的关系,就像上文提到的,有父节点、子节点、前驱节点、后继节点、第一个子节点、最后一个子节点等等。

方法:检查节点是否有子节点。
1.3.3 DOM 集合
DOM 集合是一个类数组的可迭代对象,不是一个数组。其特点:
- 可迭代性。可以用
for...of
迭代; - 不是数组。不可使用未继承的数组方法。(使用转换为数组、绑定数组方法变通)
- 只读。DOM 集合都是只读的,无法通过直接修改获取的
childNodes
集合,来修改DOM树中的节点。 - 实时。除了特例,几乎所有的DOM集合都是实时的,反应了DOM的当前状态。
- 整理特例!
通常不会使用for...in
遍历,使用该方法,会便利该对象下所有可枚举(enumerable)的属性,会额外遍历出很少用的属性。
1.3.4 基本导航(navigation)属性
兄弟节点(Sibling) 是指有同一个父节点的节点。
某元素的导航(navigation)属性:
不区分节点类型:
-
访问后继兄弟节点:
elem.nextSibling
-
访问前驱兄弟节点:
elem.previousSibling
-
访问父节点:
elem.parentNode
-
访问第一个子节点:
-
访问最后一个子节点:
只导航元素类型:
- 访问后继兄弟元素节点:
nextElementSibling
- 访问前驱兄弟元素节点:
previousElementSibling
- 访问父元素节点:
elem.parentElement
- 访问第一个元素子节点:
elem.firstElementChild
- 访问最后一个元素子节点:
elem.lastElementChild
注:
-
在绝大多数情况下,
elem.parentElement
和elem.parentNode
都会返回同一个父节点。例外的是,document.documentELement
。根元素document.documentElement
指向<html>
,其父节点就是document
根节点,但是#document
不是一个元素节点,所以访问parentElement
会返回null
。document.documentElement.parentNode // document
document.documentElement.parentElement // null
1.3.4.1 表格(table)
表格节点拥有额外的导航属性:
<table>
拥有额外的属性:
table.rows
:指向<tr>
元素的集合;table.rows[i]
:可访问第 i 个单元格。
table.caption
:指向元素<caption>
;table.tHead
:指向元素<thead>
;table.tFoot
:指向元素<tfoot>
;table.tBodies
:指向<tbody>
元素的集合。
<thead>
,<tfoot>
,<tbody>
元素提供了 rows
属性:
tbody.rows